#include "pisplayer.h"
#include "ui_pisplayer.h"
#include "InterfaceMsg.h"
#include "configclass.h"
#include "environment.h""

#include "DES.h"

#include <QFontDatabase>

//注意，版本号应该在程序内部修改，开机程序会自动修改配置文件内的版本号
//如果想添加或者删除license和demo，在main中把相应的define去除
//license还要在pro文件中把添加license的库添加上
//#define LICENSE

//CEPIDS 这个自定义是在CE中当播放器使用的
//#define CEPIDS
//1

QStringList findCurPathCEPro(const QString& path);

ProcessSignalObject g_processSigObject;

void processSysSignal(int signal)
{
//    printf("...test1test111test111test111...............>>>%d\n", signal);
//    g_processSigObject.sendVdecProgress();
    if (signal == SIGTERM)
    {
        g_processSigObject.processRebootSignal();
    } else if (signal == SIGKILL){
        g_processSigObject.processPowerOffSignal();
    } else if (signal == SIGHUP)
    {
        g_processSigObject.processINTSignal();
    }
    return;
}

PISPlayer::PISPlayer(const QString state, QWidget *parent) :
    QWidget(parent), m_updateState(state),
    ui(new Ui::PISPlayer)
{
     logger()->info("slcd is starting ...... !!!\n");

     QString lastSchedulePro;

//#ifdef _TTY_POSIX_
//    signal(SIGTERM, processSysSignal);
//    signal(SIGKILL, processSysSignal);
//    signal(SIGHUP, processSysSignal);
//#endif

     connect(&g_processSigObject, SIGNAL(signal_sysPoweroff()), this, SLOT(processSysPoweroff()));
     connect(&g_processSigObject, SIGNAL(signal_sysReboot()), this, SLOT(processSysReboot()));

    ui->setupUi(this);

#ifdef CEPIDS
    QDesktopWidget* desktop = QApplication::desktop();
    setGeometry(0, 0, desktop->width(), GLOBAL_RESOLUTION_HEIGHT);
    this->setFixedSize(desktop->width(), GLOBAL_RESOLUTION_HEIGHT);
#else
    setWindowFlags(Qt::FramelessWindowHint);
    this->setCursor(Qt::BlankCursor);
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    setGeometry(0, 0, GLOBAL_RESOLUTION_WIDTH, GLOBAL_RESOLUTION_HEIGHT);
    this->checkShowScreen();
//      this->setAttribute(Qt::WA_NoBackground);
#endif

    setWindowIcon(QIcon("PISPlayer.ico"));
    this->setAutoFillBackground(false);
    QPalette palette;
    palette.setColor(QPalette::Background, QColor(0, 0, 0));
    this->setPalette(palette);

    m_nCarNum = (configclass.getCarNum() - 1) * 2 + 2;


    //从配置中取出当前的路线播放列表名和当前列车同内位置
    lastSchedulePro = configclass.getScheduleProName();
    QString strSide = configclass.getCarSideStr();
    //b-side = left-side = 1
    //a-side = right-side = 2
    //TIS发出的命令是有左右侧的
    if( (strSide == "B") || (strSide == "b") || (strSide == "l") || (strSide == "L"))
    {
        m_nSide = 1;
    }
    else
    {
        m_nSide = 2;
    }
    m_nPosition = m_nCarNum;

    m_playlist = new PlayList((QObject*)this);
    connect(this, SIGNAL(receUpdateConfig()), m_playlist, SIGNAL(updateConfig()));


    QString xmlProPath = g_installPath + "/";
    QString xmlProName = configclass.getScheduleProName();
#ifdef CEPIDS
    if (xmlProName.isEmpty())
      {
          findLastVersion();
      } else {
          xmlProPath = xmlProPath + xmlProName + ".CEPrj";
          QFile file;
          if (!file.exists(xmlProPath))
          {
              findLastVersion();
          } else {
              proStruct = xmlParser.parsetProFile(xmlProPath);
          }
      }
#else
    /*
     开机启动后会从配置中取出当前的路线播放列表文件，如果找不到相对应的线路列表文件，
     那么从当前路径中找到最新的路线列表文件并加载，并更新进配置文件中
     线路列表文件以　.CEPrj 结尾,如　pro20120210.CEPrj
    */
    if (xmlProName.isEmpty())
    {
        findLastVersion();
    } else {
        xmlProPath = xmlProPath + xmlProName + ".CEPrj";
        proStruct = xmlParser.parsetProFile(xmlProPath);

        //文件不对或者找不到，那么从而查找最新的资源列表文件
        if (proStruct.dbPath.isEmpty())
        {
            findLastVersion();         
        } else {
            logger()->info("load project:%1 and it's path is %2\n", lastSchedulePro, g_installPath);
        }
    }
#endif

    m_isStart = true;

    bool bLoad = false;
    if (proStruct.proPath.isEmpty() && proStruct.dbPath.isEmpty() && proStruct.resoucePath.isEmpty())
    {
        configclass.setScheduleProName("");
        configclass.setScheduleVersion("");
        configclass.setResourceSize(0);
        configclass.sync();
        logger()->warn(tr("Can't find schedule file\n"));
    } else {

        bLoad = m_playlist->Load(proStruct.dbPath, proStruct.resoucePath);
        if (bLoad)
        {

            QFileInfo info(proStruct.proPath);
            configclass.setScheduleProName(info.baseName());
            configclass.setScheduleVersion(proStruct.publishTime);
            configclass.setResourceSize(proStruct.resourceSize);
            logger()->info("load project:%1 fail, but find new project: %2 and it's path is %3\n",
                           lastSchedulePro, info.baseName(), g_installPath);

            logger()->info(tr("Success to open database:%1\n").arg(proStruct.dbPath));

        } else {
            logger()->error(tr("Fail to open database:%1\n").arg(proStruct.dbPath));
        }
    }


    RouteMsgStruct routeMsg;
    routeMsg.routeCode = "0";
    routeMsg.currentStationCode = "0";
    routeMsg.positionIncar = 0/*1*/;
    routeMsg.trainStatusID = 0;

    //更新列车信息，刚开机时播放默认背景
    if (bLoad)
        m_playlist->updateTranInfo(routeMsg);

#ifdef _TTY_POSIX_
    this->playLocalInfomation();
#endif


#ifdef CEPIDS
    udpThread = new UdpSocketThread(3333, this);
    udpThread->start();
    connect(udpThread, SIGNAL(receCtlCmd(PIDS_ControlPIDS)), this, SLOT(receCtlCmd_solt(PIDS_ControlPIDS)));
    connect(udpThread, SIGNAL(receRouteMsg(PIDS_RouteMsg)), this, SLOT(receRouteMsg_solt(PIDS_RouteMsg)));
#else
    QString strCom = configclass.getTISCom();
    int nBaud = configclass.getTISBaud();
//    QStringList listFsm = configclass.getFsmList();

    //H146 Software Design Document_rev2.pdf中6.2.3 command package from TIS
    //列车两侧对应不同的代码，一个接收一个回复
    // side        接收/回复
    //a-side        40/50
    //b-side        45/55
    QStringList listFsm;
    if( (configclass.getCarSideStr() == "A") || (configclass.getCarSideStr() == "a") || (configclass.getCarSideStr() == "R") || (configclass.getCarSideStr() == "r"))
    {
        listFsm.append("40");
        listFsm.append("50");
    } else {
        listFsm.append("45");
        listFsm.append("55");
    }
    bool ok = false;
    int nFsm[2] = {0};
    for(int i=0; i<listFsm.count(); i++)
    {
        nFsm[i] = listFsm.at(i).toInt(&ok, 16);
    }

    m_tis = new Tis(nFsm[0], nFsm[1], this);
    connect(m_tis, SIGNAL(msgArrive(IMsg*)), this, SLOT(recvMsg(IMsg*)));
    m_tis->OpenPort(strCom, nBaud);

    //网络处理模块
    serverWidget = new ServerWidget(m_updateState.toInt(), this);
    connect(serverWidget, SIGNAL(updateConfig()), this, SLOT(updateConfig()));
    connect(serverWidget, SIGNAL(sendVideoStatus(QList<LCDSTATUS>,bool)), this, SLOT(sendVideoStatusToTIS(QList<LCDSTATUS>,bool)));
    connect(serverWidget, SIGNAL(receCheckLcdCmd(qint8)), this, SLOT(receCheckLcdCmd(qint8)));

    connect(m_tis, SIGNAL(selfTest()), serverWidget, SLOT(checkVidoStatu()));
#endif

#ifdef _TTY_POSIX_
    //路线资源文件更新模块
    updateFile = new UpdateFile(this);
    connect(updateFile, SIGNAL(startToUpdate(int,QString)), this, SLOT(startToUpdate(int,QString)));
    connect(updateFile, SIGNAL(updateFinish(int,ProjectStruct)), this, SLOT(updateFinish(int,ProjectStruct)));
    connect(updateFile, SIGNAL(umountUsbState(int)), this, SLOT(umountUsb(int)));
#endif
    checkNote();

#ifdef DEMOVERSION
    //demo提醒模块
    m_demoMsgBox = new QMessageBox(this);
    m_demoMsgBox->setIcon(QMessageBox::Warning);
    m_demoMsgBox->setText("This is a demo version");
    m_demoMsgBox->setStandardButtons(QMessageBox::Ok);
    connect(m_demoMsgBox->button(QMessageBox::Ok), SIGNAL(clicked()), this, SLOT(demoMsgBoxOk()));

    QFont font;
    font.setPixelSize(25);
    m_demoMsgBox->setFont(font);
    m_demoMsgBox->setFixedSize(400, 200);
    m_demoMsgBox->hide();

    //半个钟提醒一次
    m_demoTimer = new QTimer(this);
    m_demoTimer->setSingleShot(true);
    m_demoTimer->start(60 * 30 * 1000);
//    m_demoTimer->start(2 * 1000);
    connect(m_demoTimer, SIGNAL(timeout()), this, SLOT(showDemoDialog()));
#endif

}

//查找版本最新的数据文件
void PISPlayer::findLastVersion()
{
    QList<ProjectStruct> proStructList;
    QStringList xmlProList;
    xmlProList = findCurPathCEPro(g_installPath);

    for(int i = 0; i < xmlProList.count(); i++)
    {
        ProjectStruct strcut;
        strcut = xmlParser.parsetProFile(xmlProList.at(i));
        if (proStructList.count() == 0)
        {
            proStructList.append(strcut);
        } else {
            for(int j = 0; j < proStructList.count(); j++)
            {
                if (proStructList.at(j).publishTime < strcut.publishTime)
                {
                    proStructList.insert(j, strcut);
                }
            }
        }
    }

    QFile file;
    QDir dir;
    for(int i = 0; i < proStructList.count(); i++)
    {
//        qDebug() << proStructList.at(i).dbPath << proStructList.at(i).resoucePath;
        QString resourcePath = g_installPath + "/" + proStructList.at(i).resoucePath;
        if (file.exists(proStructList.at(i).dbPath) && dir.exists(resourcePath))
        {
            proStruct = proStructList.at(i);
        }
    }

    QString resourpath = g_installPath + "/" + proStruct.resoucePath;
    qint64 countDirSize = this->countDirSize(resourpath);
    proStruct.resourceSize = countDirSize;
}

//计算文件夹的大小
qint64 PISPlayer::countDirSize(const QString& dirPath)
{

#ifdef _TTY_POSIX_
    struct stat     stat;
    struct dirent   *dirp;
    DIR             *dp;
    char            *ptr;

    ptr = (char *)malloc(sizeof(char) * 1024);

    int fileSize = 0;

    dp = opendir(dirPath.toLatin1().data());
    if (dp == NULL)
    {
//        qDebug() << "open dp err==>" << dirPath.toLatin1().data();
        return fileSize;
    }

    while((dirp = readdir(dp)) != NULL)
    {
        if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
        {
            continue;
        }

        memset(ptr, 0, 1024);
        strcpy(ptr, dirPath.toLatin1().data());
        strcat(ptr, "/");
        strcat(ptr, dirp->d_name);
        if (lstat(ptr, &stat) < 0)
        {
            continue;
        }

        if (!S_ISDIR(stat.st_mode))
        {
            fileSize += stat.st_size;
        } else {
            QString dirPath = QString::fromLocal8Bit(ptr);
            fileSize += this->countDirSize(dirPath);
        }
    }

    //linux中每个文件夹也占4096个字节，右键属性中的大小已经包含这个大小,所以要算占用空间的大小
    //这个是要加进去，不过在WIN下只计算纯粹大小，所以此处不加进去
    //fileSize += 4096;

//    qDebug() << fileSize << "ptr===>" << dirPath;

    free(ptr);
    closedir(dp);
    return fileSize;
#else

    //linux下用此算法基本正确，但如果有涉及到中文名字，那么中文名将不能识别，
    //从而导致大小计算出错
    QDir dir(dirPath);
    QFileInfoList infoList = dir.entryInfoList();

    qint64 fileSize = 0;

    for(int i = 0; i < infoList.count(); i++)
    {
        QFileInfo info = infoList.at(i);

        if(info.fileName() == "." || info.fileName() == "..")
            continue;

        if (dirPath.contains("PISPlayer-build-desktop/Resource/AD"))
            qDebug() << infoList.count() << i << "infoFileName===>:" << info.fileName();

        if (info.isDir())
        {
            fileSize += this->countDirSize(info.absoluteFilePath());
        } else {
            fileSize += info.size();
        }
    }
    fileSize += 4096;

    return fileSize;
#endif
}

//检验日志文件的日期，如果超过保留日期，那么删除
void PISPlayer::checkNote()
{
    QString notePath = QCoreApplication::applicationDirPath() + "/log4j.properties";
    QFile file(notePath);
    if (!file.open(QIODevice::ReadOnly))
    {
        return;
    }

    //从配置中读取日志路径
    QTextStream stream(&file);
    QString path;
    while(!stream.atEnd())
    {
        path = stream.readLine(100);
        if (path.contains(".R.File"))
        {
            path = path.remove(0, path.indexOf("=")+1);
            path = path.remove(path.lastIndexOf("/"), path.length() - path.lastIndexOf("/"));
            path = QCoreApplication::applicationDirPath() + "/" + path;
            break;
        }
    }
    //将之保存到全局变量中，后面客户端下载要用到此路径
    g_NotePath = path;
    QDir dir(path);
    dir.setFilter(QDir::Files);

    QFileInfoList list = dir.entryInfoList();
    int fileCount = list.count();

    //文件检测，超过保留日期的将之删除
    for(int i = 0; i < fileCount; i++)
    {
        QFileInfo fileInfo = list.at(i);
        QDate creatDate = QDate::fromString(fileInfo.created().toString("yyyyMMdd"), "yyyyMMdd");
        QDate currentDate = QDate::currentDate();
        int reserveDays = configclass.getSysReserveDays();
        if (creatDate.daysTo(currentDate) > reserveDays)
        {
            file.remove(fileInfo.filePath());
        }
    }
}

///<
void PISPlayer::checkShowScreen()
{
    QDesktopWidget *desktop = qApp->desktop();
    QSize resolution;

    //screen index from 0
    int primaryScreen = desktop->primaryScreen();
    int screenCount = desktop->screenCount();
    int showScreenIndex = configclass.showScreenIndex();
//    int num = 0;
//    int width = 0;

    resolution.setWidth(desktop->width());
    resolution.setHeight(desktop->height());

    QPoint pos;
    if (showScreenIndex > 0 && ((showScreenIndex+1) <= screenCount))
    {

        QRect rect = desktop->screenGeometry(showScreenIndex);
        pos.setX(rect.x());
        pos.setY(rect.y());
        this->resize(rect.width(), GLOBAL_RESOLUTION_HEIGHT);
        this->move(pos);
    } else {
        this->move(0, 0);
        QRect rect = desktop->screenGeometry(showScreenIndex);
        this->resize(rect.width(), GLOBAL_RESOLUTION_HEIGHT);
    }

//    qDebug()<<"width:"<<width << "num:" << num;

    logger()->info(tr("\n\nscreen count:%3, primary screen index:%4, "
                      "show screen index:%5\n\n").arg(screenCount).arg(primaryScreen+1).arg(showScreenIndex));

//    qDebug() << tr("\n\nscreen count:%3, primary screen index:%4, "
//                   "show screen index:%5\n\n").arg(screenCount).arg(primaryScreen+1).arg(showScreenIndex);

}

//播放初始信息
// 2) Display Controller在每次開機/ 開始SLCD程式的時候,rr
//先播放自己的IP ADDRESS, 日期, 時間, CAR NO, Left/ Right side 的信息
void PISPlayer::playLocalInfomation()
{
    QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName());

    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    QString address;

    foreach(QHostAddress hostAddress, list)
    {
        if (hostAddress.protocol() == QAbstractSocket::IPv4Protocol)
        {
            address = hostAddress.toString();
        }
    }

    QString carNo = tr("%1").arg(configclass.getCarNum());
    QString carSide = tr("%1").arg(configclass.getCarSideStr());

    QString date = QDate::currentDate().toString("yyyy-MM-dd");
    QString time = QTime::currentTime().toString("hh:mm:ss");
    int second = configclass.getBroadcastInfoTime();

    QString msg = "\n\n                        **********************************************************************\n";

    msg.append("\n                                                 IP ADDRESS:   ");
    msg.append(address);


    msg.append("\n                                                 Date:                 ");
    msg.append(date);

    msg.append("\n                                                 Time:                ");
    msg.append(time);

    msg.append("\n                                                 CAR NO.:          ");
    msg.append(carNo);

    msg.append("\n                                                 CAR Side:          ");
    msg.append(carSide);

    msg.append("\n\n                        **********************************************************************");
//    qDebug() << "msg===========>" << msg;
    m_playlist->playInfomation(second, msg);
}

PISPlayer::~PISPlayer()
{
    logger()->info("slcd shut down ...... !!!\n\n\n\n");

    delete ui;
//    qDebug() << "~PISPlayer 000";

    if(m_playlist)
    {
        delete m_playlist;
    }
//    qDebug() << "~PISPlayer 111";
#ifdef CEPIDS
    if (udpThread)
    {
        udpThread->quit();
        udpThread->wait(100);
//        delete udpThread;
    }
#else
    if (serverWidget)
    {
        delete serverWidget;
    }
//    qDebug() << "~PISPlayer 222";

    if(m_tis)
    {
        delete m_tis;
    }
//    qDebug() << "~PISPlayer 333";

#endif

#ifdef _TTY_POSIX_
    if (updateFile)
    {
        delete updateFile;
    }
#endif

}


void PISPlayer::updateConfig()
{
    emit receUpdateConfig();

    Configclass configclass;
    m_nCarNum = (configclass.getCarNum() - 1) * 2 + 2;


    QString strSide = configclass.getCarSideStr();
    if( (strSide == "B") || (strSide == "b") || (strSide == "l") || (strSide == "L"))
    {
        m_nSide = 1;
    }
    else
    {
        m_nSide = 2;
    }
    m_nPosition = m_nCarNum;


#ifndef CEPIDS
    QString strCom = configclass.getTISCom();
    int nBaud = configclass.getTISBaud();

    QStringList listFsm;
    if( (configclass.getCarSideStr() == "A") || (configclass.getCarSideStr() == "a") || (configclass.getCarSideStr() == "R") || (configclass.getCarSideStr() == "r"))
    {
        listFsm.append("40");
        listFsm.append("50");
    } else {
        listFsm.append("45");
        listFsm.append("55");
    }
    bool ok = false;
    int nFsm[2] = {0};
    for(int i=0; i<listFsm.count(); i++)
    {
        nFsm[i] = listFsm.at(i).toInt(&ok, 16);
    }

    if (m_tis == NULL)
    {
        m_tis = new Tis(nFsm[0], nFsm[1], this);
        connect(m_tis, SIGNAL(msgArrive(IMsg*)), this, SLOT(recvMsg(IMsg*)));
    } else {
        m_tis->closePort();
        m_tis->setSeq(nFsm[0], nFsm[1]);
    }
    m_tis->OpenPort(strCom, nBaud);
#endif
}

void PISPlayer::receCheckLcdCmd(const qint8 cmd)
{
    m_playlist->chcekLcd(cmd);
}

void PISPlayer::recvMsg(IMsg* msg)
{
    try
    {
        if(msg != NULL)
        {
            if(msg->base.msgType == MSG_TIS)
            {
                pisToTisPkg msgPkg;
                memcpy(&msgPkg, msg->body, sizeof(msgPkg));//只适用于测试


                RouteMsgStruct routeMsg;
                routeMsg.routeCode = QString::number(msgPkg.routeID, 16);
                routeMsg.currentStationCode = QString::number(msgPkg.stationID, 16);
                routeMsg.trainStatusID = msgPkg.status/*QString::number(msgPkg.status, 10)*/;

                //对于车厢开门侧的计算，如果是platform side信号时，必须记录当前车门要开的方向，B／left side(1)，A／right side(2), both(3);
                //所以要如果相等即为同一侧否则为反侧开门
                //信号来时，先查找对应的car位置，如果没有查找对应的开门侧,这一侧(all platform side)/对侧(all non-platform side),
                //如果还是没有的话就查找所有位置(all position)

                routeMsg.positionIncar = 0;
                int carPosition = configclass.getCarNum() * 2;


                if (msgPkg.platSide != 3)
                {
                    if (msgPkg.platSide != 0)
                    {
                        if (msgPkg.platSide == m_nSide)
                        {
                            routeMsg.positionIncar += 1;
                        } else {
                            routeMsg.positionIncar += 2;
                        }
                        routeMsg.positionIncar += carPosition;
                    } else {
                        routeMsg.positionIncar = 0;
                    }
                } else {
                    routeMsg.positionIncar = 0;
                }
                m_playlist->updateTranInfo(routeMsg);
//                this->hide();
//                this->show();
//                this->updateGeometry();
            }

        }
    }
    catch(...)
    {

    }
//    this->update();
//    this->hide();
//    this->repaint();
}


void PISPlayer::playfinish()
{
    //pMPlayer->play(g_g_installPath+"/pkg4/a02.mpg");
}

void PISPlayer::playfinish1()
{
    // pMPlayer1->play(g_g_installPath+"/pkg4/a02.mpg");
}


//开始更新
void PISPlayer::startToUpdate(const int proCount, const QString &publishTime)
{
    QString updateMsg;
    if (proCount <= 0)
    {
        updateMsg = tr("\n\n\n      Find the USB flash drive,search the update sources    ");
    } else {
        QDateTime dateTime;
        dateTime = dateTime.fromString(publishTime, "yyyyMMddhhmm");
        updateMsg = tr("\n\n\n      Updating...Find %1 update sources,the lastest version is %2 \n      start to update      ").arg(proCount).arg(dateTime.toString("yyyy-MM-dd,hh:mm:ss"));

        updateStruct.updateProCount = proCount;
        updateStruct.publishTime = publishTime;
        updateStruct.receUpdateCount = 0;
        updateStruct.msgList.clear();
    }

    updateMsg = QString::fromLocal8Bit(updateMsg.toLatin1());
    m_playlist->updateDataState(0, updateMsg);
    this->update();
}

//更新完成
void PISPlayer::updateFinish(const int condition, const ProjectStruct &project)
{
    //    qDebug() << "=========================<<<PISPlayer:updateFinish>>>==============================";

    Configclass configclass;
    updateStruct.receUpdateCount++;

    QString updateMsg;
    if (condition >= 0)
    {
        updateMsg = tr("Success to update");

        QString xmlProPath = g_installPath + "/";
        QString xmlProName = configclass.getScheduleProName();

        if (xmlProName.isEmpty())
        {
            findLastVersion();
        } else {
            xmlProPath = xmlProPath + xmlProName + ".CEPrj";
            proStruct = xmlParser.parsetProFile(xmlProPath);
        }

        m_playlist->Load(proStruct.dbPath, proStruct.resoucePath);

    } else {
        //err：-1,xml解析出错;-2,当前版本为最新的;-3,拷贝数据库错；-4,拷贝资源文件出错;-5,挂载U盘失败; -6,更新文件不齐全; -7,更新失败，回复备份失败;

        switch(condition)
        {
        case -1:
            updateMsg = tr("Update failed,parse xml-file error ");
            break;
        case -2:
            updateMsg = tr("Update failed,the current version is the lastest");
            break;
        case -3:
            updateMsg = tr("Update failed,fail to copy the database ");
            break;
        case -4:
            updateMsg = tr("Update failed,fail to copy the resource ");
            break;
        case -5:
            updateMsg = tr("Update failed,fail to mount the USB flash drive ");
            break;
        case -6:
            updateMsg = tr("Update failed,update file is not complete ");
            break;
        case -7:
            updateMsg = tr("Update failed，not back up file ");
            break;
        case -8:
            updateMsg = tr("Update failed，back up file is not complete ");
            break;
        default:
            updateMsg = tr("Update failed,other errors ");
            break;
        }
    }
    QString msg = updateMsg;

    updateStruct.msgList.append(updateMsg);

    if (condition != 5)
    {
        //        QString msg = tr("第%1个源更新完成：%2,开始更新第%3个源").arg(updateStruct.receUpdateCount).arg(updateMsg).arg(updateStruct.receUpdateCount+1);
        //        msg = QString::fromLocal8Bit(msg.toLatin1());
        //        m_playlist->updateDataState(1, msg);

        QDateTime dateTime;
        dateTime = dateTime.fromString(updateStruct.publishTime, "yyyyMMddhhmm");

        QString proName;
        if (condition >= 0)
        {
            int index = project.proPath.lastIndexOf("/");

            proName = project.proPath;
            proName = proName.remove(0, index+1);

            updateMsg = tr("\n\n\n      Find %1 update sources,the lastest version is %2 \n      project name:%3, resource size:%4,\n      %5 ").
                    arg(updateStruct.updateProCount).arg(dateTime.toString("yyyy-MM-dd,hh:mm:ss"))
                    .arg(proName).arg(project.resourceSize).arg(updateMsg);
        } else {
            updateMsg = tr("\n\n\n      Find %1 update sources,the lastest version is %2 \n      %3 ").arg(updateStruct.updateProCount).arg(dateTime.toString("yyyy-MM-dd,hh:mm:ss")).arg(updateMsg);
        }
        QString StringUpdateMsg = updateMsg + ",uninstall USB flash drive,Please wait ";

        StringUpdateMsg = QString::fromLocal8Bit(StringUpdateMsg.toLatin1());
        updateMsg = QString::fromLocal8Bit(updateMsg.toLatin1());
        m_updateMsg = updateMsg;
        m_playlist->updateDataState(0, StringUpdateMsg);

        logger()->info(tr("Update resource:Find %1 update sources;the lastest version is %2;project name:%3;resource size:%4;%5\n").
                       arg(updateStruct.updateProCount).arg(dateTime.toString("yyyy-MM-dd hh:mm:ss"))
                       .arg(proName).arg(project.resourceSize).arg(msg));

    } else {
        updateMsg = QString::fromLocal8Bit(updateMsg.toLatin1());
        m_updateMsg = updateMsg;
        m_playlist->updateDataState(0, m_updateMsg);
    }
}



/*******************************************
  功能：接收到线路信息命令，ce通过tcp模拟tis发送线路信息
        然后本机进行处理
  参数：
  返回值：
  ******************************************/
void PISPlayer::receRouteMsg_solt(const PIDS_RouteMsg& routeMsg)
{
    CeRouteMsg ceRouteMsg;
    ceRouteMsg.routeID = routeMsg.routeID;
    ceRouteMsg.destID = routeMsg.destID;
    ceRouteMsg.platSide = routeMsg.doorSide;
    ceRouteMsg.status = routeMsg.status;
    ceRouteMsg.stationID = routeMsg.stationID;
    ceRouteMsg.directionID = routeMsg.directionID;

//    if (g_stDebugConfig.isDebugTisCtl)
//    {
//        QStringList list1;
//        list1 << "STATUS_CABOCCUPIED" << "STATUS_REST" << "STATUS_DOOROPEN" << "STATUS_DOORCLOSE" << "STATUS_TRAVELING" \
//              << "STATUS_PLATFORMDOOR" << "STATUS_CABUNOCCUPIED";
//        QString status = list1.at(ceRouteMsg.status-1);
//        qDebug() << ceRouteMsg.destID << "ceRouteMsg====>" << status << ceRouteMsg.routeID << ceRouteMsg.stationID << ceRouteMsg.destID << ceRouteMsg.directionID;
//    }

    //对于车厢开门侧的计算，如果是platform side信号时，必须记录当前车门要开的方向，B／left side(1)，A／right side(2), both(3);
    //所以要如果相等即为同一侧否则为反侧开门
    //信号来时，先查找对应的car位置，如果没有查找对应的开门侧,这一侧(all platform side)/对侧(all non-platform side),
    //如果还是没有的话就查找所有位置(all position)

    ceRouteMsg.positionIncar = 0;
    int carPosition = configclass.getCarNum() * 2;


    if (ceRouteMsg.platSide != 3)
    {
        if (ceRouteMsg.platSide != 0)
        {
            if (ceRouteMsg.platSide == m_nSide)
            {
                ceRouteMsg.positionIncar += 1;
            } else {
                ceRouteMsg.positionIncar += 2;
            }
            ceRouteMsg.positionIncar += carPosition;
        } else {
            ceRouteMsg.positionIncar = 0;
        }
    } else {
        ceRouteMsg.positionIncar = 0;
    }
    m_playlist->updateCeTranInfo(ceRouteMsg);

}

/*******************************************
  功能：收到关闭命令，那么程序退出,主要是在ce下才有用
  参数：
  返回值：
  ******************************************/
void PISPlayer::receCtlCmd_solt(const PIDS_ControlPIDS& cltPids)
{
    if (cltPids.BaseFiles.SubCmd == SUBCMD_CLOSEPIDSACK)
    {
//        this->close();
        qApp->exit(444);
    } else {
        qApp->exit(773);
    }
}

/*******************************************
  功能：USB卸载状态提醒，界面上显示提醒
  参数：state,卸载状态
  返回值：
  ******************************************/
void PISPlayer::umountUsb(const int state)
{
    QString updateMsg;
    if (state >= 0)
    {
        updateMsg = tr(",unplug the USB flash drive please      ");
    } else {
        updateMsg = tr(",faile to uninstall USB flash drive,unplug the USB flash drive please      ");
    }



    updateMsg = QString::fromLocal8Bit(updateMsg.toLatin1());
    m_updateMsg.append(updateMsg);
    m_playlist->updateDataState(1, m_updateMsg);
    this->update();
    this->updateConfig();

//    qDebug() << "dbPath:" << proStruct.dbPath
//             << "resourcepath:" << proStruct.resoucePath;

    m_playlist->Load(proStruct.dbPath, proStruct.resoucePath);
}


/*******************************************
  功能：上报LCD屏状态给TIS
  参数：status,LCD的状态列表，isTisSelfTest,TIS是否有申请自检,没有不上报LCD状态给TIS
  返回值：
  ******************************************/
void PISPlayer::sendVideoStatusToTIS(const QList<LCDSTATUS> &status, const bool isTisSelfTest)
{

#ifdef _TTY_POSIX_
    if (!isTisSelfTest)
        return;

    if (configclass.getReplortState() <= 0)
            return;
//    The answer package to TIS is as follows:
//    STX　TYPE     ANS     ETX   BCC (H)   BCC (L)
//    02H　1 byte   1 byte　03H 　1 byte    1 byte

//  TYPE:	Type of equipment to be controlled.
//              30H:	EDD (Existing Unit)
//              31H:	ETND (Existing Unit)
//              40H:    Display Controller(right side)
//              45H:    Display Controller(left side)


//              50H:	SLCD A1     right side
//              51H	SLCD A2
//              52H	SLCD A3
//              53H	SLCD A4
//              54H	SLCD A5
//              55H	SLCD B1     left side
//              56H	SLCD B2
//              57H	SLCD B3
//              58H	SLCD B4
//              59H	SLCD B5

//              ANS:	Control commands.
//              30H:	Correct
//              31H:	BCC error
//              32H:	Length error
//              33H:	Format error
//              34H:	Display fault

//              BCC:	Block Check Character

    QList<PanelInfoStruct> panelInfoList;
    panelInfoList = configclass.getSLCDInfoIntList();
    //2012.8.3 如果LpanelID不是1-5那么...
    for(int i = 0; i < status.count(); i++)
    {
        for(int j = 0; j < panelInfoList.count(); j++)
        {
            if (panelInfoList.at(j).panelID == status.at(i).panelID)
            {
                int panelID = j;
                qint8 state;
                if (status.at(i).videoStatus == 0x31 || status.at(i).videoStatus == 0x32)
                {
                    state = 0x30;
                } else {
                    state = 0x34;
                }
                if( (configclass.getCarSideStr() == "A") || (configclass.getCarSideStr() == "a") || (configclass.getCarSideStr() == "R") || (configclass.getCarSideStr() == "r"))
                {
                    panelID += 0x50;
                } else {
                    panelID += 0x55;
                }

                if (panelID != 0 && status.at(i).isCollect > 0)
                {
//                    qDebug() << "send to Tis" << panelID << (qint8)status.at(i).videoStatus;
                    m_tis->sendToTis(panelID, (qint8)state);
                }
                break;
            }
        }
    }
#endif
}

/*******************************************
  功能：demo模块关闭和显示
  参数：
  返回值：
  ******************************************/
void PISPlayer::showDemoDialog()
{
#ifdef DEMOVERSION
    if (m_demoMsgBox->isVisible())
    {
        m_demoMsgBox->hide();
        m_demoTimer->start(60 * 30 * 1000);
//        m_demoTimer->start(2 * 1000);

    } else {
//        m_demoTimer->start(2 * 1000);
        m_demoTimer->start(10 * 1000);
        m_demoMsgBox->show();
    }
#endif
}


void PISPlayer::processSysReboot()
{
    logger()->info("system reboot ...... !!!\n");
    this->close();
}

void PISPlayer::demoMsgBoxOk()
{
//    qDebug() << "<<<<<<<<<<<<< PISPlayer demoMsgBoxOk >>>>>>>>>>>>";
#ifdef DEMOVERSION
    m_demoMsgBox->hide();
    m_demoTimer->stop();
    m_demoTimer->start(60 * 30 * 1000);
//    m_demoTimer->start(2 * 1000);
#endif
}

void PISPlayer::processSysPoweroff()
{
    logger()->info("system power off ...... !!!\n");
    this->close();
}

char* get_exe_path()
{
    static char buff[256];
    char *p;

#if defined(WIN32)
    ::GetModuleFileName(NULL, buff, sizeof(buff));
    p = strrchr(buff, '\\');
#else
    int pid;

    pid = getpid();
    sprintf(buff, "/proc/%d/exe", pid);
    readlink(buff, buff, sizeof(buff));
    p = strrchr(buff, '/');
#endif
    *p = 0;
    return buff;
}


/*******************************************
  功能：查找当前路线文件
  参数：
  返回值：
  ******************************************/
QStringList findCurPathCEPro(const QString& path)
{
    QDir dir(path);
    QFileInfoList fileInfoList = dir.entryInfoList();
    QStringList fileList;

    foreach(QFileInfo fileInfo, fileInfoList)
    {
        if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            continue;

        if(!fileInfo.isDir())
        {
            if (fileInfo.fileName().contains(".CEPrj"))
            {
                fileList.append(fileInfo.absoluteFilePath());
            }
        }
    }
    return fileList;
}


